import { _decorator, Component, find, Node, UITransform, Vec3, math, Rect, Sprite, Color, AudioClip, AudioSource, EventTouch } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Weapon')
export class Weapon extends Component {
    @property(AudioClip)
    selectAudio: AudioClip = null!

    @property(AudioClip)
    putAudio: AudioClip = null!

    backpack: Node = new Node()
    backpackCover: Node = new Node()

    box: Node = new Node()
    boxCover: Node = new Node()

    weaponLayoutNode: Node = new Node()
    targetCover: Node = null;

    axeDirTemp: string = ''                         // 斧头情况特殊，该变量用来临时记录符合条件的两个网格节点排列方向
    originalPos: Vec3 = new Vec3()                  // 当前武器节点的初始位置
    targetGridItemArray: any[] = []                 // 用于武器放置的网格数组
    audioSource: AudioSource = new AudioSource()
    private _selected: boolean = false;

    get selected() {
        return this._selected;
    }

    set selected(value) {
        this._selected = value;
    }

    start() {
        this.addEvents()
        this.backpack = find('Canvas/Backpack')
        this.backpackCover = find('Canvas/Backpack Cover')
        this.box = find('Canvas/Box')
        this.boxCover = find('Canvas/BoxCover')
        this.weaponLayoutNode = find('Canvas/Weapon Layout')
        this.audioSource = find('Canvas').getComponent(AudioSource)
    }

    /** 
     * @zh
     * 添加监听事件。
    */
    addEvents() {
        this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this)
        this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this)
        this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this)
        this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this)
    }

    /** 
     * @zh
     * 当节点被触摸时执行的逻辑。
    */
    onTouchStart(event) {
        // 记录初始位置
        this.originalPos = new Vec3(this.node.position)
        this.audioSource.playOneShot(this.selectAudio)

        if (this.node.parent.name.includes("Cover")) {
            this.node.setSiblingIndex(this.node.parent.children.length - 1)
        }
        this.selected = true;
        // 重置斧头的相关变量
        this.axeDirTemp = ''
    }

    private checkIntersectedGridItems(node: Node): number {
        // 获取到所有和当前武器节点相交的网格
        let intersectedGridItemArray = this.getIntersectedGridItems(node);
        if (!intersectedGridItemArray || !intersectedGridItemArray.length) {
            return
        } else {
        }

        console.log(intersectedGridItemArray.length)

        // 图片名称中包含当前图片所占网格数的信息，开发者可以把该信息放在武器JSON文件中
        let occupiedGridNum = parseInt(this.node.name.split('-')[1])

        // 图片名称中包含当前图片方向，开发者可以把该信息放在武器JSON文件中
        // h表示横向
        // v表示纵向
        // vh表示既有横向又有纵向
        // n表示没有，即占用单个网格
        let dir = this.node.name.split('-')[2]

        // 根据占用的网格数拿到和武器节点相交区域最大的网格节点，并将这些节点的颜色改变
        let count = 0
        this.targetGridItemArray = []
        if (dir != "vh") {
            count = this.checkNormalIntersected(intersectedGridItemArray, dir, occupiedGridNum)
        } else {
            count = this.checkAxeIntersected(intersectedGridItemArray, occupiedGridNum)
        }

        return count;
    }

    private checkNormalIntersected(intersectedGridItemArray: Node[], dir: string, occupiedGridNum: number): number {
        let count = 0
        let lastGridItem = null
        for (let i = 0; i < intersectedGridItemArray.length; i++) {
            if (count >= occupiedGridNum) {
                break
            }

            if (!lastGridItem) {
                intersectedGridItemArray[i][0].getComponent(Sprite).color = new Color(100, 100, 100)
                this.targetGridItemArray.push(intersectedGridItemArray[i][0])
                lastGridItem = intersectedGridItemArray[i][0]
                count += 1
            }
            else {
                if (dir == 'v' && lastGridItem.position.x == intersectedGridItemArray[i][0].position.x) {
                    intersectedGridItemArray[i][0].getComponent(Sprite).color = new Color(100, 100, 100)
                    this.targetGridItemArray.push(intersectedGridItemArray[i][0])
                    lastGridItem = intersectedGridItemArray[i][0]
                    count += 1
                }
                else if (dir == 'h' && lastGridItem.position.y == intersectedGridItemArray[i][0].position.y) {
                    intersectedGridItemArray[i][0].getComponent(Sprite).color = new Color(100, 100, 100)
                    this.targetGridItemArray.push(intersectedGridItemArray[i][0])
                    lastGridItem = intersectedGridItemArray[i][0]
                    count += 1
                }
            }
        }
        return count;
    }

    private checkAxeIntersected(intersectedGridItemArray: Node[], occupiedGridNum: number): number {
        if (intersectedGridItemArray.length < occupiedGridNum) {
            return 0
        }
        let isOk = false
        let tempNd = [].concat(intersectedGridItemArray.slice(0, occupiedGridNum));
        tempNd.sort((na: any, nb: any) => {
            if (na[0].position.x != nb[0].position.x) {
                return na[0].position.x - nb[0].position.x;
            }
            return nb[0].position.y - na[0].position.y;
        })
        let grid0 = tempNd[0][0]
        let grid1 = tempNd[1][0]
        let grid2 = tempNd[2][0]

        let curAngle = this.node.angle;
        switch (curAngle) {
            case 0: // 0  没有左下
                if (grid0.position.y == grid1.position.y && grid1.position.x == grid2.position.x) {
                    isOk = true
                }
                break;
            case 90:// 90 没有右下
                if (grid0.position.x == grid1.position.x && grid0.position.y == grid2.position.y) {
                    isOk = true
                }
                break;
            case 180: // 180 没有右上
                if (grid1.position.y == grid2.position.y && grid0.position.x == grid1.position.x) {
                    isOk = true
                }
                break;
            case 270:// 270 没有左上
                if (grid0.position.y == grid2.position.y && grid1.position.x == grid2.position.x) {
                    isOk = true
                }
                break;
        }

        let count = 0
        // 符合条件的话就高亮
        if (isOk) {
            for (let i = 0; i < occupiedGridNum; i++) {
                tempNd[i][0].getComponent(Sprite).color = new Color(100, 100, 100)
                this.targetGridItemArray.push(tempNd[i][0])
                count++;
            }
        }
        return count
    }

    /** 
     * @zh
     * 当节点被按下并移动时执行的逻辑。
    */
    onTouchMove(event: EventTouch) {
        // 移动武器节点
        let delta = event.getDelta()
        this.node.setPosition(new Vec3(this.node.position).add3f(delta.x, delta.y, 0))

        this.checkIntersected()
    }

    private checkIntersected(): void {
        let intersectedBackPackCnt = this.checkIntersectedGridItems(this.backpack);
        if (!intersectedBackPackCnt) {
            let intersectedBoxCnt = this.checkIntersectedGridItems(this.box);
            if (intersectedBoxCnt) {
                this.targetCover = this.boxCover;
                this.resetGird(this.backpack)
            }
        } else {
            this.targetCover = this.backpackCover;
            this.resetGird(this.box)
        }
    }

    /** 
     * @zh
     * 获取与当前武器节点相交的所有网格，并按照相交区域排序。
    */
    getIntersectedGridItems(node: Node) {
        let intersectedGridItemArray = []
        for (let i = 0; i < node.children.length; i++) {
            let gridItem = node.children[i]

            // 恢复网格颜色
            gridItem.getComponent(Sprite).color = new Color(255, 255, 255)

            // 斧头武器作特殊判断
            if (this.node.name.indexOf('p8') > -1) {
                // 拿到斧头武器这个特殊形状的包围盒。
                let axeBoundingBoxArray = this.getAxeBoundingBox(this.node, true)

                // 判断拿到的这三份包围盒和网格节点是否有相交
                for (let j = 0; j < axeBoundingBoxArray.length; j++) {
                    // 获取相交区域
                    let intersectionResult = new Rect()
                    math.Rect.intersection(intersectionResult,
                        axeBoundingBoxArray[j],
                        gridItem.getComponent(UITransform).getBoundingBoxToWorld())

                    if (intersectionResult.width > 0 && intersectionResult.height > 0) {
                        let intersectedArea = intersectionResult.width * intersectionResult.height
                        intersectedGridItemArray.push([gridItem, intersectedArea])
                    }
                }

            }
            else {
                // 获取相交区域
                let intersectionResult = new Rect()
                math.Rect.intersection(intersectionResult,
                    this.node.getComponent(UITransform).getBoundingBoxToWorld(),
                    gridItem.getComponent(UITransform).getBoundingBoxToWorld())

                if (intersectionResult.width > 0 && intersectionResult.height > 0) {
                    let intersectedArea = intersectionResult.width * intersectionResult.height
                    intersectedGridItemArray.push([gridItem, intersectedArea])
                }
            }
        }

        intersectedGridItemArray.sort((a, b) => b[1] - a[1])
        return intersectedGridItemArray
    }

    /** 
     * @zh
     * 拿到斧头武器这个特殊形状的包围盒。
    */
    getAxeBoundingBox(axeNode: Node, isToWorld: boolean = false) {
        let temp = new Rect()

        if (isToWorld) {
            temp = axeNode.getComponent(UITransform).getBoundingBoxToWorld()  // 原始的世界坐标下的包围盒
        }
        else {
            temp = axeNode.getComponent(UITransform).getBoundingBox()  // 原始的本地坐标下的包围盒
        }
        // 分割成四份，不要左下的那一块
        let axeBoundingBoxArray = []
        let axeBoundingBoxLT = new Rect(temp.x, temp.y + temp.height / 2, temp.width / 2, temp.height / 2)
        let axeBoundingBoxRT = new Rect(temp.x + temp.width / 2, temp.y + temp.height / 2, temp.width / 2, temp.height / 2)
        let axeBoundingBoxRB = new Rect(temp.x + temp.width / 2, temp.y, temp.width / 2, temp.height / 2)
        let axeBoundingBoxLB = new Rect(temp.x, temp.y, temp.width / 2, temp.height / 2)
        axeNode.angle != 270 && axeBoundingBoxArray.push(axeBoundingBoxLT)
        axeNode.angle != 180 && axeBoundingBoxArray.push(axeBoundingBoxRT)
        axeNode.angle != 90 && axeBoundingBoxArray.push(axeBoundingBoxRB)
        axeNode.angle != 0 && axeBoundingBoxArray.push(axeBoundingBoxLB)

        // console.log(this.node.angle, axeBoundingBoxLT, axeBoundingBoxRT, axeBoundingBoxRB, axeBoundingBoxLB, axeBoundingBoxArray)
        // this.node.angle == 0 90 180 270
        return axeBoundingBoxArray

    }

    /** 
     * @zh
     * 当触摸取消时执行的逻辑。
    */
    onTouchCancel(event) {
        this.putWeapon()
    }

    /** 
     * @zh
     * 当触摸结束时执行的逻辑。
    */
    onTouchEnd(event) {
        this.putWeapon();
    }

    private resetGridColor(): void {
        this.resetGird(this.backpack)
        this.resetGird(this.box)
    }

    private resetGird(node: Node): void {
        for (let i = 0; i < node.children.length; i++) {
            let gridItem = node.children[i]
            // 恢复网格颜色
            gridItem.getComponent(Sprite).color = new Color(255, 255, 255)
            gridItem = null
        }
    }

    rotateWeapon(): void {
        this.node.angle = (this.node.angle + 90) % 360;
        let nameArr = this.node.name.split('-')
        let dir = nameArr[2]
        if (dir == "v") {
            this.node.name = `${nameArr[0]}-${nameArr[1]}-h`
        } else if (dir == "h") {
            this.node.name = `${nameArr[0]}-${nameArr[1]}-v`
        }

        this.checkIntersected()
    }

    /** 
     * @zh
     * 放置武器。
    */
    putWeapon() {
        this.selected = false;
        this.resetGridColor()

        // 如果没有符合的相交网格，则直接返回
        if (this.targetGridItemArray.length == 0) {
            console.log("err----111>")
            this.node.setPosition(this.originalPos)
            return
        }

        // 图片名称中包含当前图片所占网格数
        let occupiedGridNum = parseInt(this.node.name.split('-')[1])

        // 不符合的网格数量，则不放置
        if (this.targetGridItemArray.length < occupiedGridNum) {
            console.log("err----222>")
            this.node.setPosition(this.originalPos)
            return
        }

        // 条件符合，放置武器，放在网格或网格们的中间位置
        let x = 0
        let y = 0
        for (let i = 0; i < this.targetGridItemArray.length; i++) {
            x += this.targetGridItemArray[i].position.x
            y += this.targetGridItemArray[i].position.y
        }
        x = x / this.targetGridItemArray.length
        y = y / this.targetGridItemArray.length

        // 如果是斧头的话，由于图片原因，最终位置可以向左下偏移一点，这里可以自行调整
        let deltaX = this.targetGridItemArray[0].getComponent(UITransform).width / 6
        let deltaY = this.targetGridItemArray[0].getComponent(UITransform).height / 6
        if (this.node.name.indexOf('p8') > -1) {
            switch (this.node.angle) {
                case 0:
                    x -= deltaX
                    y -= deltaY
                    break;
                case 90:
                    x += deltaX
                    y -= deltaY
                    break;
                case 180:
                    x += deltaX
                    y += deltaY
                    break;
                case 270:
                    x -= deltaX
                    y += deltaY
                    break;
            }

        }

        this.targetCover.addChild(this.node)
        this.node.setPosition(x, y, 0)
        this.node.setSiblingIndex(0);

        // 判断有没有和其他已放置武器的相交，有的话把之前的武器从背包中移除，添加回Weapon Layout节点中。
        this.putCoveredWeaponBack(this.targetCover)

        this.audioSource.playOneShot(this.putAudio)
    }

    /** 
     * @zh
     * 判断有没有和其他已放置武器的相交，有的话把之前的武器从背包中移除，添加回Weapon Layout节点中。
    */
    putCoveredWeaponBack(node: Node) {
        let intersectedWeaponItemArray = []
        for (let i = 0; i < node.children.length; i++) {
            let weaponItem = node.children[i]
            if (weaponItem == this.node) {
                continue
            }

            // 如果玩家当前移动其他武器，目标要判断的weaponItem是斧头，则将斧头的世界包围盒分成四份， 丢弃左下角那块
            if (weaponItem.name.indexOf('p8') > -1) {
                // 拿到斧头武器这个特殊形状的包围盒。
                let axeBoundingBoxArray = this.getAxeBoundingBox(weaponItem)

                // 判断拿到的这三份包围盒和网格节点是否有相交
                for (let j = 0; j < axeBoundingBoxArray.length; j++) {
                    let intersectionResult = new Rect()
                    math.Rect.intersection(intersectionResult,
                        this.node.getComponent(UITransform).getBoundingBox(),
                        axeBoundingBoxArray[j])

                    if (intersectionResult.width > 0 && intersectionResult.height > 0) {
                        intersectedWeaponItemArray.push(weaponItem)
                    }
                }

            }
            else if (this.node.name.indexOf('p8') > -1) {
                // 拿到斧头武器这个特殊形状的包围盒。
                let axeBoundingBoxArray = this.getAxeBoundingBox(this.node)

                // 判断拿到的这三份包围盒和网格节点是否有相交
                for (let j = 0; j < axeBoundingBoxArray.length; j++) {
                    let intersectionResult = new Rect()
                    math.Rect.intersection(intersectionResult,
                        axeBoundingBoxArray[j],
                        weaponItem.getComponent(UITransform).getBoundingBox())

                    if (intersectionResult.width > 0 && intersectionResult.height > 0) {
                        intersectedWeaponItemArray.push(weaponItem)
                    }
                }
            }
            else {
                let intersectionResult = new Rect()
                math.Rect.intersection(intersectionResult,
                    this.node.getComponent(UITransform).getBoundingBox(),
                    weaponItem.getComponent(UITransform).getBoundingBox())

                if (intersectionResult.width > 0 && intersectionResult.height > 0) {
                    intersectedWeaponItemArray.push(weaponItem)
                }
            }
        }

        for (let i = 0; i < intersectedWeaponItemArray.length; i++) {
            this.weaponLayoutNode.addChild(intersectedWeaponItemArray[i])
        }
    }
}


